﻿Imports System.Net
Imports System.IO
Imports System.Text

Public Class WebRequestHelper

    Property ContentType As String = "application/x-www-form-urlencoded"

    Property cookie As CookieContainer

    Property AcceptLanguage As String

    Property Accept As String = "*/*"

    Property UserAgent As String

    Property TimeOut As Integer = 5000

    Property AllowAutoRedirect As Boolean = True

    Public Function HttpGet(ByVal url As String, ByVal querydata As Dictionary(Of String, String)) As String
        If querydata IsNot Nothing AndAlso querydata.Count > 0 Then
            url += "?" + String.Join("&", querydata.Select(Function(it) Convert.ToString(it.Key) & "=" & Convert.ToString(it.Value)))
        End If
        Return HttpGet(url)
    End Function

    ''' <summary>
    ''' FenderAPI
    ''' </summary>
    ''' <param name="url"></param>
    ''' <param name="querydata"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function HttpGetFender(ByVal url As String, ByVal querydata As Dictionary(Of String, String)) As String
        If querydata IsNot Nothing AndAlso querydata.Count > 0 Then
            Try
                Dim request As HttpWebRequest = CreateWebRequest(url)
                request.Method = "GET"
                For Each qd In querydata
                    request.Headers.Add(qd.Key, qd.Value)
                Next
                Using request.GetResponse
                    Dim response As HttpWebResponse = DirectCast(request.GetResponse, HttpWebResponse)
                    Dim json As String = New StreamReader(response.GetResponseStream, Encoding.UTF8).ReadToEnd
                    Return json
                End Using
            Catch ex As Exception
                Return ex.ToString
            End Try
        End If
        Return String.Empty
    End Function


    Public Function HttpGet(ByVal url As String) As String
        Try
            Dim request As HttpWebRequest = CreateWebRequest(url)
            request.Method = "GET"
            Using request.GetResponse
                Dim response As HttpWebResponse = DirectCast(request.GetResponse, HttpWebResponse)
                Dim json As String = New StreamReader(response.GetResponseStream, Encoding.UTF8).ReadToEnd
                Return json
            End Using
        Catch ex As Exception
            Return ex.ToString
        End Try
    End Function

    Public Function HttpGet(ByVal url As String, ByVal querydata As Dictionary(Of String, String), ByRef response As HttpWebResponse) As String
        If querydata IsNot Nothing AndAlso querydata.Count > 0 Then
            url += "?" + String.Join("&", querydata.Select(Function(it) Convert.ToString(it.Key) & "=" & Convert.ToString(it.Value)))
        End If
        Return HttpGet(url, response)
    End Function

    Public Function HttpGet(ByVal url As String, ByRef response As HttpWebResponse) As String
        Dim request As HttpWebRequest = CreateWebRequest(url)
        request.Method = "GET"
        Using request.GetResponse
            response = DirectCast(request.GetResponse, HttpWebResponse)
            Dim json As String = New StreamReader(response.GetResponseStream, Encoding.UTF8).ReadToEnd
            Return json
        End Using
    End Function

    Public Function HttpPost(ByVal url As String, ByVal postdata As Dictionary(Of String, String)) As String
        Dim postDataStr As String = ""
        If postdata IsNot Nothing AndAlso postdata.Count > 0 Then
            postDataStr = String.Join("&", postdata.Select(Function(it) Convert.ToString(it.Key) & "=" & Convert.ToString(it.Value)))
        End If
        Return HttpPost(url, postDataStr)
    End Function

    Public Function HttpPost(ByVal url As String, ByVal postdata As String) As String
        Try
            Dim request As HttpWebRequest = CreateWebRequest(url)
            request.Method = "POST"
            If String.IsNullOrWhiteSpace(postdata) = False Then
                Dim bytesToPost = Encoding.UTF8.GetBytes(postdata)
                request.ContentLength = bytesToPost.Length
                Using requestStream As Stream = request.GetRequestStream
                    requestStream.Write(bytesToPost, 0, bytesToPost.Length)
                    requestStream.Close()
                End Using
            End If
            Using response As HttpWebResponse = DirectCast(request.GetResponse, HttpWebResponse)
                Using sr As StreamReader = New StreamReader(response.GetResponseStream(), Encoding.UTF8)
                    Return sr.ReadToEnd
                End Using
            End Using
        Catch ex As Exception
            Return ex.ToString
        End Try
    End Function

    Public Function HttpPost(ByVal url As String, ByVal filename As String, ByVal fileData As Stream) As String
        Dim request As HttpWebRequest = CreateWebRequest(url)
        request.Method = "POST"
        Dim boundary As String = "---------------" + DateTime.Now.Ticks.ToString("x")
        Dim formData As String = ""
        If fileData IsNot Nothing Then
            Dim formName As String = "media"
            Dim sb As StringBuilder = New StringBuilder()
            sb.Append("--")
            sb.Append(boundary)
            sb.Append(vbCrLf)
            sb.Append("Content-Disposition: form-data; name=""" + formName + """; filename=""" + filename + """")
            sb.Append(vbCrLf)
            sb.Append("Content-Type: application/octet-stream")
            sb.Append(vbCrLf)
            sb.Append(vbCrLf)
            formData = sb.ToString
        End If
        Using postStream As MemoryStream = New MemoryStream
            Dim formdataBytes = Encoding.UTF8.GetBytes(formData)
            postStream.Write(formdataBytes, 0, formdataBytes.Length)
            Dim buffer(1023) As Byte
            Dim bytesRead As Integer = fileData.Read(buffer, 0, buffer.Length)
            While (bytesRead > 0)
                postStream.Write(buffer, 0, bytesRead)
                bytesRead = fileData.Read(buffer, 0, buffer.Length)
            End While
            Dim footer As Byte() = Encoding.UTF8.GetBytes(vbCrLf + "--" + boundary + "--" + vbCrLf)
            postStream.Write(footer, 0, footer.Length)
            request.ContentType = String.Format("multipart/form-data;boundary={0}", boundary)
            request.ContentLength = postStream.Length
            request.Accept = "text/html,application+xml;q=0.9,image/webp,*/*;q=0.8"
            request.KeepAlive = True
            request.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36"
            postStream.Position = 0
            Using requestStream As Stream = request.GetRequestStream()
                Dim reqBuffer(1023) As Byte
                Dim reqBytesRead As Integer = postStream.Read(reqBuffer, 0, reqBuffer.Length)
                While reqBytesRead > 0
                    requestStream.Write(reqBuffer, 0, reqBytesRead)
                    reqBytesRead = postStream.Read(reqBuffer, 0, reqBuffer.Length)
                End While
                postStream.Close()
                Dim response As HttpWebResponse = DirectCast(request.GetResponse, HttpWebResponse)
                Using responseStream As Stream = response.GetResponseStream()
                    Using myStreamReader As StreamReader = New StreamReader(responseStream, Encoding.UTF8)
                        Return myStreamReader.ReadToEnd
                    End Using
                End Using
            End Using
        End Using
    End Function

    Public Function HttpPost(ByVal url As String, ByVal postdata As String, ByVal cer As System.Security.Cryptography.X509Certificates.X509Certificate) As String
        Dim request As HttpWebRequest = CreateWebRequest(url)
        request.ClientCertificates.Add(cer)
        request.Method = "POST"
        If String.IsNullOrWhiteSpace(postdata) = False Then
            Dim bytesToPost = Encoding.UTF8.GetBytes(postdata)
            request.ContentLength = bytesToPost.Length
            Using requestStream As Stream = request.GetRequestStream
                requestStream.Write(bytesToPost, 0, bytesToPost.Length)
                requestStream.Close()
            End Using
        End If
        Using response As HttpWebResponse = DirectCast(request.GetResponse, HttpWebResponse)
            Using sr As StreamReader = New StreamReader(response.GetResponseStream(), Encoding.UTF8)
                Return sr.ReadToEnd
            End Using
        End Using
    End Function


    Public Function HttpUploadFile(ByVal url As String, ByVal file As String, ByVal postdata As Dictionary(Of String, String)) As String
        Return HttpUploadFile(url, file, postdata, Encoding.UTF8)
    End Function

    Public Function HttpUploadFile(ByVal url As String, ByVal file As String, ByVal postdata As Dictionary(Of String, String), ByVal encoding As Encoding) As String
        Return HttpUploadFile(url, New String() {file}, postdata, encoding)
    End Function

    Public Function HttpUploadFile(ByVal url As String, ByVal files As String(), ByVal postdata As Dictionary(Of String, String)) As String
        Return HttpUploadFile(url, files, postdata, Encoding.UTF8)
    End Function

    Public Function HttpUploadFile(ByVal url As String, ByVal files As String(), ByVal postdata As Dictionary(Of String, String), ByVal encoding__1 As Encoding) As String
        Dim boundary As String = "---------------------------" & DateTime.Now.Ticks.ToString("x")
        Dim boundarybytes As Byte() = Encoding.ASCII.GetBytes(vbCrLf & "--" & boundary & vbCrLf)
        Dim endbytes As Byte() = Encoding.ASCII.GetBytes(vbCrLf & "--" & boundary & "--" & vbCrLf)

        Dim request As HttpWebRequest = CreateWebRequest(url)
        request.ContentType = "multipart/form-data; boundary=" & boundary
        request.Method = "POST"
        request.KeepAlive = True

        request.AllowAutoRedirect = Me.AllowAutoRedirect
        If Me.cookie IsNot Nothing Then
            request.CookieContainer = Me.cookie
        End If
        request.Credentials = CredentialCache.DefaultCredentials

        Using stream As Stream = request.GetRequestStream()
            Dim formdataTemplate As String = "Content-Disposition: form-data; name=""{0}""" & vbCrLf & vbCrLf & "{1}"
            If postdata IsNot Nothing Then
                For Each key As String In postdata.Keys
                    stream.Write(boundarybytes, 0, boundarybytes.Length)
                    Dim formitem As String = String.Format(formdataTemplate, key, postdata(key))
                    Dim formitembytes As Byte() = encoding__1.GetBytes(formitem)
                    stream.Write(formitembytes, 0, formitembytes.Length)
                Next
            End If
            Dim headerTemplate As String = "Content-Disposition: form-data; name=""{0}""; filename=""{1}""" & vbCrLf & "Content-Type: application/octet-stream" & vbCrLf & vbCrLf
            Dim buffer(4095) As Byte
            Dim bytesRead As Integer = 0
            For i As Integer = 0 To files.Length - 1
                stream.Write(boundarybytes, 0, boundarybytes.Length)
                Dim header As String = String.Format(headerTemplate, "file" & i, Path.GetFileName(files(i)))
                Dim headerbytes As Byte() = encoding__1.GetBytes(header)
                stream.Write(headerbytes, 0, headerbytes.Length)
                Using fileStream As New FileStream(files(i), FileMode.Open, FileAccess.Read)
                    Dim fileBytesRead As Integer = fileStream.Read(buffer, 0, buffer.Length)
                    While fileBytesRead <> 0
                        stream.Write(buffer, 0, fileBytesRead)
                        fileBytesRead = fileStream.Read(buffer, 0, buffer.Length)
                    End While
                End Using
            Next
            stream.Write(endbytes, 0, endbytes.Length)
        End Using
        Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
        Using stream As New StreamReader(response.GetResponseStream())
            Return stream.ReadToEnd()
        End Using
    End Function

    Public Function GetResponseImage(ByVal url As String) As Stream
        Try
            Dim request As HttpWebRequest = CreateWebRequest(url)
            request.KeepAlive = True
            request.Method = "GET"
            Dim response As HttpWebResponse = DirectCast(request.GetResponse, HttpWebResponse)
            Return response.GetResponseStream
        Catch ex As Exception
            Return Nothing
        End Try
    End Function

    Public Function CreateWebRequest(ByVal url As String) As HttpWebRequest
        Dim request As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
        request.ContentType = Me.ContentType
        If Me.cookie IsNot Nothing Then
            request.CookieContainer = Me.cookie
        End If
        If String.IsNullOrEmpty(Me.AcceptLanguage) Then
            Dim myWebHeaderCollection As WebHeaderCollection = request.Headers
            myWebHeaderCollection.Add("Accept-Language", Me.AcceptLanguage)
        End If
        request.Accept = Me.Accept
        request.UseDefaultCredentials = True
        request.UserAgent = Me.UserAgent
        request.Timeout = Me.TimeOut
        request.AllowAutoRedirect = Me.AllowAutoRedirect
        Me.SetCertificatePolicy()
        Return request
    End Function

    Private Sub SetCertificatePolicy()
        ServicePointManager.ServerCertificateValidationCallback = AddressOf RemoteCertificateValidate
    End Sub

    Private Function RemoteCertificateValidate(sender As Object, certificate As System.Security.Cryptography.X509Certificates.X509Certificate, chain As System.Security.Cryptography.X509Certificates.X509Chain, sslPolicyErrors As System.Net.Security.SslPolicyErrors) As Boolean
        Return True
    End Function

End Class
